package com.ytjj.qmyx.mall.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alipay.api.*;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.github.pagehelper.util.StringUtil;
import com.google.common.collect.Lists;
import com.ytjj.common.api.CommonResult;
import com.ytjj.common.api.ResultCode;
import com.ytjj.common.constants.*;
import com.ytjj.common.constants.AlipayConstants;
import com.ytjj.common.dto.mqdto.SmsDto;
import com.ytjj.common.enums.AlipayExpressEnum;
import com.ytjj.common.enums.PlatformEnum;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.exception.GlobalExceptionHandler;
import com.ytjj.common.model.UsersResponse;
import com.ytjj.common.model.YxAlipayConfig;
import com.ytjj.common.model.request.AliyunMallRequest;
import com.ytjj.common.service.RedisService;
import com.ytjj.common.utils.*;
import com.ytjj.common.utils.feishu.FeiShuUtil;
import com.ytjj.qmyx.mall.client.FreightTemplateClient;
import com.ytjj.qmyx.mall.constants.ExpireTimeConstant;
import com.ytjj.qmyx.mall.constants.FormConstant;
import com.ytjj.qmyx.mall.constants.RedisConstants;
import com.ytjj.qmyx.mall.constants.*;
import com.ytjj.qmyx.mall.enums.*;
import com.ytjj.qmyx.mall.mapper.*;
import com.ytjj.qmyx.mall.model.*;
import com.ytjj.qmyx.mall.model.dto.RecordSubsidyDataDto;
import com.ytjj.qmyx.mall.model.request.AlipayOrderRequest;
import com.ytjj.qmyx.mall.model.EffectParamRequest;
import com.ytjj.qmyx.mall.model.request.YxAlipayTradeWapPayRequest;
import com.ytjj.qmyx.mall.model.response.AlipayNotifyResponse;
import com.ytjj.qmyx.mall.model.response.ReturnCouponResponse;
import com.ytjj.qmyx.mall.service.*;
import com.ytjj.qmyx.mall.utils.AlipayFactoryUtils;
import com.ytjj.qmyx.mall.utils.Base64Util;
import com.ytjj.qmyx.users.client.UsersClient;
import com.ytjj.qmyx.users.model.DefaultAddressDto;
import com.ytjj.qmyx.users.model.UserBalanceDto;
import com.ytjj.qmyx.users.model.UsersDto;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;


/**
 * @Description 阿里云支付
 *
 * @Version 1.0
 * 
 */

@Service
@Slf4j
@RefreshScope
public class AlipayServiceImpl implements AlipayService {

    @Resource
    private AlipayConstants alipayConstants;

    @Resource
    private AlipayConstants05 alipayConstants05;
    @Resource
    private AlipayCertConstants alipayCertConstants;

    @Resource
    private OrdersPayMapper ordersPayMapper;

    @Resource
    private OrdersMapper ordersMapper;

    @Resource
    private OrdersDao ordersDao;

    @Resource
    private OrdersInfoMapper ordersInfoMapper;

    @Resource
    private ProductService productService;

    @Resource
    private CopyWriterConfigUtil copyWriterConfigUtil;

    @Resource
    private AlipayUtil alipayUtil;

    @Resource
    private UsersClient usersClient;

    @Resource
    private RedisService redisService;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private DynamicDao dynamicDao;
    @Autowired
    public OrdersService ordersService;
    @Autowired
    private GroupActivityService groupActivityService;
    @Value("${order.push.switch:false}")
    private Boolean orderPushSwitch;//订单实时推送开关
    @Value("${brokerageRatio:1.6}")
    private String brokerageRatio;
    @Value("${subsidyDay:7}")
    private String subsidyDay;
    //是否计算运费 1-计算 0-不计算
    @Value("${yunfeiSwitch:0}")
    private String yunfeiSwitch;
    @Value("${paySucReturnUrl.channel:ssvip,kq,vip,xvip,kvip}")
    private String paySucReturnUrl;
    @Resource
    private DynamicMapper dynamicMapper;
    @Resource
    private HelpWorkInfoDao helpWorkInfoDao;
    @Autowired
    private FreightTemplateClient freightTemplateClient;
    @Resource
    private AdvertCallBackService advertCallBackService;

    @Resource
    private PayConfigDao payConfigDao;
    @Resource
    private AlipayFactoryUtils alipayFactory;

    @Value("${baiduToken:FnMsmoneZfIY1SS7AGekqFfYcq1LlIcu@I0rZjsLf9rRbosPGVorrB8ylDwBeFMFj}")
    private String baiduToken;

    //限制下单地址
    @Value("${order.blackAddress:公安局,派出所,检察院,法院,工商局}")
    private String blackAddress;
    //飞书预警下单数量
    @Value("${checkOrderNum:8}")
    private Integer checkOrderNum;



    public AlipayTradeAppPayResponse alipayMobile(String resOrderNo,BigDecimal amount,String subject,String desc,String childId) {
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        request.setNotifyUrl(alipayConstants.getNOTIFY_URL()+"/aliPay" +"/"+childId);

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", resOrderNo);
        bizContent.put("total_amount",amount);
        bizContent.put("subject", subject);
//        bizContent.put("seller_id", alipayConstants.getAPP_APPID());
        bizContent.put("product_code", "QUICK_MSECURITY_PAY");

        bizContent.put("body", desc);
        request.setBizContent(bizContent.toString());
        AlipayTradeAppPayResponse response = null;
        try {
            log.info("alipayMobile支付宝支付参数:{}",JSON.toJSONString(request));
            response = alipayUtil.getAlipayClient(childId).sdkExecute(request);
            log.info("alipayMobile支付宝支付返回:{}",JSON.toJSONString(response));

        } catch (AlipayApiException e) {
            log.error("支付宝构造表单失败", e);
        }
        return response;
    }

    /**
     * @Description H5订单生成
     *
     *
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String h5PayOrder(AlipayOrderRequest payRequest, HttpServletResponse httpResponse, UsersResponse usersResponse) {
        Orders orders = null;
        if(StringUtils.isNotBlank(payRequest.getOrderNo())){
            orders = ordersDao.queryOrdersByOrderNo(payRequest.getOrderNo());
        } else{
            orders = ordersMapper.selectByPrimaryKey(payRequest.getOrderId());
        }
        if (orders ==null){
            throw new ApiException("订单不存在,请重新下单或者联系在线客服!");
        }
        //校验商品收货地址
        OrdersInfoExample ordersInfoExample = new OrdersInfoExample();
        ordersInfoExample.createCriteria().andOrderIdEqualTo(orders.getId());
        List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectByExample(ordersInfoExample);
        Orders finalOrders = orders;

        if ("1".equals(yunfeiSwitch)) {
            ordersInfoList.stream().forEach(ordersInfo -> {
                //获取运费模板
                FreightTemplateResponse freightTemplateResponse = ordersService.getFreightTemplateResponse(ordersInfo.getProductId());
                if (null != freightTemplateResponse) {
                    //判断是否在限制地区
                    YxAstrictRegionResponse astrictRegion = freightTemplateResponse.getAstrictRegion();
                    if (ObjectUtil.isNotNull(astrictRegion) && org.apache.commons.lang3.StringUtils.isNotBlank(astrictRegion.getRegionDesc())) {
                        String[] region = astrictRegion.getRegionDesc().split(",");
                        Optional<String> regionFlag = Stream.of(region).filter(x -> x.contains(finalOrders.getProvince())).findFirst();
                        if (regionFlag.isPresent() && regionFlag.get().contains("全境")) {
                            throw new ApiException("您所在的区域该商品不能下单，先去看看其他商品吧~");
                        }
                    }
                    if (null != astrictRegion && StringUtils.isNotBlank(astrictRegion.getRegion())) {
                        String[] region = astrictRegion.getRegion().split(",");
                        Optional<String> regionFlag = Stream.of(region).filter(x -> x.equals(finalOrders.getCity())).findFirst();
                        if (regionFlag.isPresent() && org.apache.commons.lang3.StringUtils.isNotBlank(regionFlag.get())) {
                            throw new ApiException("您所在的区域该商品不能下单，先去看看其他商品吧~");
                        }
                    }
                }
            });
        }
        log.info("===h5 order pay==={}", orders.getOrderNo());
        log.info("===IsPayConstant.YES.equals(orders.getIsPay())==={}", IsPayConstant.YES.equals(orders.getIsPay()));
        if (IsPayConstant.YES.equals(orders.getIsPay())) {
            throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.PAID));
        }
        //敏感地址限制
        if (org.apache.commons.lang3.StringUtils.isNotBlank(orders.getUserAddress()) && blackAddress!=null){
            String[] blackAddressList = blackAddress.split(",");
            for (String bd : blackAddressList) {
                if (orders.getUserAddress().contains(bd)){
                    throw new ApiException("该地区不可下单,-3");
                }
            }
        }
        payRequest.setWalletMoneyFlag(Optional.ofNullable(payRequest.getWalletMoneyFlag()).orElse(0));
        // 校验用户余额
        if (payRequest.getWalletMoneyFlag() == 1) {
            if (usersResponse.getMoney().compareTo(new BigDecimal(0)) == -1) {
                payRequest.setWalletMoneyFlag(0);
            }
        }

        // 取出第一条子订单
        OrdersInfo ordersInfo = ordersInfoList.get(0);

        orders.setIsInvoice(null == payRequest.getIsInvoice() ? 0 : payRequest.getIsInvoice());
        try {
            // 获取生成的订单号
            String resOrderNo = OrderUtils.getPayOrderCode(orders.getUserId());
            OrdersPay pay = new OrdersPay();
            pay.setAmount(orders.getRealTotalMoney());
            pay.setOrderNo(orders.getOrderNo());
            pay.setResOrderNo(resOrderNo);
            pay.setPayType(PayPayTypeEnums.BEING_PROCESSED.getType());
            pay.setTradeType("aliPay");
            pay.setCreateTime(new Date());



            String form = "";
            try {
                String returnUrl = "";
                AlipayClient alipayClient;
                //调用SDK生成表单
                AlipayTradeWapPayRequest alipayRequest = new YxAlipayTradeWapPayRequest();

                YxAlipayConfig yxAlipayConfig = null;
                //根据配置开关是否开启订单分流
                try {
                    String orderAvg_switch = ordersDao.getSysConfig("orderAvg_switch");
                    if (StringUtils.isNotBlank(orderAvg_switch) && "true".equals(orderAvg_switch)){
                        String alipayAvg_account = ordersDao.getSysConfig("alipayAvg_account");
                        if (StringUtils.isNotBlank(alipayAvg_account)){
                            String[] avgAccount = alipayAvg_account.split(",");
                            int randomValue = (int)(Math.random() * (avgAccount.length)) ;
                            String zfbAccount = avgAccount[randomValue];
                            log.info("h5pay随机支付宝账号:{}",zfbAccount);
                            yxAlipayConfig = payConfigDao.findAliPayByAccount(zfbAccount);
                            if (yxAlipayConfig==null){
                                yxAlipayConfig = payConfigDao.findAliPayByState();
                            }
                        }else{
                            yxAlipayConfig = payConfigDao.findAliPayByState();
                        }
                    }else{
                        yxAlipayConfig = payConfigDao.findAliPayByState();
                    }
                } catch (Exception e) {
                    log.info("订单分流报错,{}",e.getMessage());
                    yxAlipayConfig = payConfigDao.findAliPayByState();
                }

                //默认走数据库配置
                if (yxAlipayConfig!=null){
                    alipayClient = alipayUtil.getAlipayClientByMysql(yxAlipayConfig);
                    // 设置异步地址
                    alipayRequest.setNotifyUrl(yxAlipayConfig.getNotifyUrl());
                    // 设置支付成功跳转地址
                    returnUrl = yxAlipayConfig.getReturnUrl();

                    pay.setPayConfigId(yxAlipayConfig.getId());
                }else{
                    alipayClient = alipayUtil.getAlipayClient(null);
                    //支付宝账号切换收款开关
                    String alipayflag =ordersDao.getSysConfig("ALI_PAY_FLAG");
                    if (StringUtils.isNotBlank(alipayflag)){
                        Map<String,String> alipayMap = JSON.parseObject(alipayflag,Map.class);
                        String aliPayCheckFlag = alipayMap.get("aliPayCheckFlag");
                        if (StringUtils.isNotBlank(aliPayCheckFlag) && "1".equals(aliPayCheckFlag)){
                            alipayClient = alipayUtil.getAlipayClient05();
                            log.info("支付宝H5支付账户切换成功");
                        }
                    }
                    // 设置异步地址
                    alipayRequest.setNotifyUrl(alipayConstants.getH5_NOTIFY_URL());
                    // 设置支付成功跳转地址
                    returnUrl = alipayConstants.getRETURN_URL();
                }

                ordersPayMapper.insertSelective(pay);
                ordersMapper.updateByPrimaryKeySelective(orders);

                if(StringUtils.isNotBlank(payRequest.getSourcePlatform())){
                    returnUrl = payRequest.getSourcePlatform();
                }
                returnUrl = returnUrl + "?orderId=" + payRequest.getOrderId() + "&payOrderId=" + pay.getId()+"&sourcePlatform="+payRequest.getSourcePlatform()+"&orderNo="+orders.getOrderNo()+"&token="+orders.getH5Token();
                String channel = TokenUtil.getChannel();
                if (StringUtil.isNotEmpty(channel)) {
                    if (!channel.contains("old")) {
                        returnUrl = returnUrl + "&channel=" + channel + "-old";
                    } else {
                        returnUrl = returnUrl + "&channel=" + channel;
                    }
                }
                alipayRequest.setReturnUrl(returnUrl);

                AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
                String productName = ordersInfo.getProductName().trim().replaceAll("%", "");
                if (productName.length() > 30) {
                    productName = productName.substring(0, 20);
                }
                model.setBody("XXXX优品h5");
                model.setSubject(productName);

                model.setOutTradeNo(resOrderNo);
                model.setTotalAmount(orders.getRealTotalMoney().toString());
                String callback = "";
                if ("h5".equals(TokenUtil.getSource()) && TokenUtil.getChannel().contains("h5-ks")) {
                    callback = TokenUtil.getRequest().getHeader("callback");
                }
                model.setPassbackParams(callback);
                alipayRequest.setBizModel(model);
                alipayRequest.putOtherTextParam("userToken", usersResponse.getToken());

                form = alipayClient.pageExecute(alipayRequest, "GET").getBody();
                if (Strings.isNotEmpty(form)) {
                    // 设置订单地址
                    orders.setOrderRemarks(payRequest.getDesc());
                    ordersMapper.updateByPrimaryKeySelective(orders);
                    return form;
                } else {
                    throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.ZFB_CREATES_ORDER_ERROR));
                }
            } catch (AlipayApiException e) {
                e.printStackTrace();
                if (!e.getMessage().contains("Duplicate entry ")){
                    FeiShuUtil.sendMsg(String.format("支付宝h5pay接口异常,%s",e.getMessage()));
                }
            }
            httpResponse.setContentType("text/html;charset=" + alipayConstants.getCHARSET());
            //直接将完整的表单html输出到页面
            httpResponse.getWriter().write(form);
            httpResponse.getWriter().flush();
            httpResponse.getWriter().close();
        } catch (Exception e) {
            log.error("支付宝支付异常，{}",e);
            if (!e.getMessage().contains("Duplicate entry ")){
                FeiShuUtil.sendMsg(String.format("支付宝h5pay接口异常,%s",e.getMessage()));
            }
        }
        return null;
    }

    /**
     * 支付宝h5支付-证书模式
     * @param orderUserId
     * @param orderRealTotalMoney
     * @param userToken
     * @param  sourcePlatform
     * @param orderId
     * @param payId
     * @return
     * @throws AlipayApiException
     */
    private String payByAlipayCertModel(Integer orderUserId, BigDecimal orderRealTotalMoney, String userToken,
                                             String sourcePlatform, Integer orderId, Integer payId, String resOrderNo) throws AlipayApiException {

        AlipayClient alipayClient = alipayUtil.getAlipayClientByCert();
        if (null == alipayClient) {
            log.error("===支付宝客户端初始化异常===");
            throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.ZFB_CREATES_ORDER_ERROR));
        }

        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        // 设置异步地址
        alipayRequest.setNotifyUrl(alipayConstants.getH5_NOTIFY_URL());

        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setBody("XXXX优品");
        model.setSubject("XXXX优品");

        // 获取生成的订单号
        model.setOutTradeNo(resOrderNo);
        model.setTotalAmount(String.valueOf(orderRealTotalMoney));
        model.setProductCode("QUICK_WAP_WAY");
//        alipayRequest.putOtherTextParam("userToken", userToken);
//        String appAuthToken = redisService.get(RedisConstants.APPAUTHTOKEN_KEY + alipayCertConstants.getAPPID());
//        if (StringUtils.isEmpty(appAuthToken)) {
//            CommonResult refreshResult = appAuthTokenByAppId(alipayCertConstants.getAPPID());
//            if (200 == refreshResult.getCode()) {
//                appAuthToken = refreshResult.getData().toString();
//            }
//        }
//        if (StringUtils.isEmpty(appAuthToken)) {
//            throw new ApiException("支付失败，请稍后重试");
//        }
//        alipayRequest.putOtherTextParam("app_auth_token", appAuthToken);//授权码
        String returnUrl = alipayConstants.getRETURN_URL();
        if(!StringUtils.isBlank(sourcePlatform)){
            List<String> taoxingou_return_url_list = null;
            if (StringUtils.isNotEmpty(paySucReturnUrl)) {
                taoxingou_return_url_list = Arrays.asList(paySucReturnUrl.split(","));
            }
            if (null != taoxingou_return_url_list && taoxingou_return_url_list.contains(sourcePlatform)) {
                returnUrl = returnUrl.replace("mall.XXXX.com", sourcePlatform + ".XXXX.com");
            }else {
                returnUrl = returnUrl.replace("mall.XXXX.com", sourcePlatform + ".XXXX.com");
            }
//            if("ssvip".equalsIgnoreCase(sourcePlatform)
//                    ||"kq".equalsIgnoreCase(sourcePlatform)
//                    ||"vip".equalsIgnoreCase(sourcePlatform)
//            || "xvip".equalsIgnoreCase(sourcePlatform)){
//                returnUrl = returnUrl.replace("h5..cn", sourcePlatform + ".taoxingou.com");
//            }else {
//                returnUrl = returnUrl.replace("h5..cn", sourcePlatform + "..cn");
//            }
        }
        // 设置同步回调地址
        alipayRequest.setReturnUrl(returnUrl + "?orderId=" + orderId + "&payOrderId=" + payId);
        //用户付款中途退出返回商户网站的地址
        model.setQuitUrl(alipayRequest.getReturnUrl());
        alipayRequest.setBizModel(model);
        log.info("===alipay wap pay request:{}", com.alibaba.fastjson.JSONObject.toJSONString(alipayRequest));
        AlipayTradeWapPayResponse response = alipayClient.pageExecute(alipayRequest);
        log.info("===alipay wap pay response:{}", com.alibaba.fastjson.JSONObject.toJSONString(response));
        if(response.isSuccess()){
            log.info("调用成功");
            return response.getBody();
        } else {
            log.info("调用失败");
        }
        return null;
    }

    /**
     * 支付宝支付-证书模式
     * @param orderUserId
     * @param orderRealTotalMoney
     * @param userToken
     * @param  sourcePlatform
     * @param orderId
     * @param payId
     * @return
     * @throws AlipayApiException
     */
    private AlipayTradeAppPayResponse payByAPPAlipayCertModel(Integer orderUserId, BigDecimal orderRealTotalMoney, String userToken,
                                             String sourcePlatform, Integer orderId, Integer payId, String resOrderNo) throws AlipayApiException {
        log.info("===APP支付宝参数===orderRealTotalMoney:{},sourcePlatform:{},orderId:{},payId:{},resOrderNo:{}",orderRealTotalMoney,sourcePlatform,orderId,payId,resOrderNo);
        AlipayClient alipayClient = alipayUtil.getAlipayClientByCert();
        if (null == alipayClient) {
            log.error("===支付宝客户端初始化异常===");
            throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.ZFB_CREATES_ORDER_ERROR));
        }

        AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
        // 设置异步地址
        alipayRequest.setNotifyUrl(alipayConstants.getNOTIFY_URL());

        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("XXXX优品");
        model.setSubject("XXXX优品");
        // 获取生成的订单号
        model.setOutTradeNo(resOrderNo);
        model.setTotalAmount(String.valueOf(orderRealTotalMoney));
//        alipayRequest.putOtherTextParam("userToken", userToken);
        String appAuthToken = redisService.get(RedisConstants.APPAUTHTOKEN_KEY + alipayCertConstants.getAPPID());
        if (StringUtils.isEmpty(appAuthToken)) {
            CommonResult refreshResult = appAuthTokenByAppId(alipayCertConstants.getAPPID());
            if (200 == refreshResult.getCode()) {
                appAuthToken = refreshResult.getData().toString();
            }
        }
        if (StringUtils.isEmpty(appAuthToken)) {
            throw new ApiException("支付失败，请稍后重试");
        }
        alipayRequest.putOtherTextParam("app_auth_token", appAuthToken);//授权码
        String returnUrl = alipayConstants.getRETURN_URL();
        if(!StringUtils.isBlank(sourcePlatform)){
            returnUrl=returnUrl.replace("h5..cn",sourcePlatform+"..cn");
        }
        // 设置同步回调地址
//        alipayRequest.setReturnUrl(returnUrl + "?orderId=" + orderId + "&payOrderId=" + payId);
        //用户付款中途退出返回商户网站的地址
//        model.setQuitUrl(alipayRequest.getReturnUrl());
        alipayRequest.setBizModel(model);
        log.info("===alipay wap pay request:{}", com.alibaba.fastjson.JSONObject.toJSONString(alipayRequest));
        AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(alipayRequest);
        log.info("===alipay wap pay response:{}", com.alibaba.fastjson.JSONObject.toJSONString(alipayTradeAppPayResponse));
        return alipayTradeAppPayResponse;
//        if(alipayTradeAppPayResponse.isSuccess()){
//            log.info("调用成功");
//            return alipayTradeAppPayResponse.getBody();
//        } else {
//            log.info("调用失败");
//        }
//        return null;
    }

    public CommonResult<AlipayTradeCreateResponse> jsapiSdkExecute(AlipayTradeCreateRequest request,String childId) {
        try {
            PayConfig payConfig = payConfigDao.findOnePayConfig(PayConfigCompanyEnum.PLATFORM.getCode(),PayConfigTypeEnum.APP.name(), PayConfigTradeTypeEnum.JSAPI.getCode());
            AlipayClient alipayClient = alipayFactory.getAlipayClient(payConfig,childId);


            request.setNotifyUrl(alipayConstants.getNOTIFY_URL()+"/aliPay-jsApi"+"/"+childId);
            log.info("支付宝小程序支付jsapiSdkExecute.request_param={}",JSON.toJSONString(request));
            AlipayTradeCreateResponse response = alipayClient.execute(request);
            log.info("支付宝小程序支付jsapiSdkExecute.response_param={}",JSON.toJSONString(response));
            return CommonResult.success(response);
        }catch (AlipayApiException e){
            log.error("调用支付宝支付异常!AlipayApiException={}",e);
            return CommonResult.failed(ResultCode.ALIPAY_ERROR,ResultCode.ALIPAY_ERROR.getMessage());
        }catch (Exception e){
            log.error("调用支付宝支付异常!Exception={}",e);
            return CommonResult.failed(ResultCode.ALIPAY_ERROR,ResultCode.ALIPAY_ERROR.getMessage());
        }
    }

    @Override
    public AlipayMerchantOrderSyncResponse syncAliPayOrder(String orderStatus,String orderNo,String orderId,Integer userId,String productName,Date createTime,String childId,String productImg) throws Exception{
        AlipayMerchantOrderSyncResponse response;
        try{
            UsersDto usersInfo = usersClient.getUsersInfo(userId);
            PayConfig payConfig = payConfigDao.findOnePayConfig(PayConfigCompanyEnum.PLATFORM.getCode(), PayConfigTypeEnum.APP.name(), PayConfigTradeTypeEnum.JSAPI.getCode());
            AlipayClient alipayClient = alipayFactory.getAlipayClient(payConfig,childId);

            OrdersInfoExample example = new OrdersInfoExample();
            example.createCriteria().andOrderIdEqualTo(Integer.parseInt(orderId));
            List<OrdersInfo> ordersInfos = ordersInfoMapper.selectByExample(example);

            String appId;
            if (StringUtils.isNotBlank(childId) && "1".equals(childId)) {
                appId = alipayConstants.getCHILD_JSAPI_APPID();
            } else {
                appId = alipayConstants.getJSAPI_APPID();
            }

//            if (orderStatus.equals("CREATE")) {
//                uploadImage(alipayClient,productImg,Integer.parseInt(orderId));
//            }
            String materialId = uploadImage(alipayClient,productImg,Integer.parseInt(orderId));
            AlipayMerchantOrderSyncRequest syncRequest = new AlipayMerchantOrderSyncRequest();
            AlipayMerchantOrderSyncModel model = new AlipayMerchantOrderSyncModel();
            model.setOrderCreateTime(createTime);
            model.setOrderModifiedTime(new Date());
            model.setOutBizNo(orderNo.substring(1));
            model.setBuyerId(usersInfo.getAlipayUserId());
            model.setOrderType("SERVICE_ORDER");
            List<OrderExtInfo> extInfo = new ArrayList<>();
            OrderExtInfo orderExtInfo = new OrderExtInfo();
            orderExtInfo.setExtKey("merchant_order_status");
            orderExtInfo.setExtValue(orderStatus);
            extInfo.add(orderExtInfo);

            OrderExtInfo orderExtInfo3 = new OrderExtInfo();
            orderExtInfo3.setExtKey("merchant_biz_type");
            orderExtInfo3.setExtValue("KX_SHOPPING");
            extInfo.add(orderExtInfo3);

            OrderExtInfo orderExtInfo4 = new OrderExtInfo();
            orderExtInfo4.setExtKey("merchant_order_link_page");

            String orderUrl;
            if ("CREATE".equals(orderStatus)) {
                String format1="pages/webView/webView?url=/pages/order/orderDetails.html%3FproductData=";
                String format = String.format("{\"orderNo\":\"%s\",\"orderId\":\"%s\"}",orderNo,orderId);
                orderUrl = format1+format;
            } else if ("CLOSED".equals(orderStatus)){
                orderUrl ="pages/webView/webView?url=/pages/subsidy/index.html";
            } else {
                String format1="pages/webView/webView?url=/pages/order/subOrderDetails.html%3F";
                String format = String.format("childOrderNo=%s",ordersInfos.get(0).getChildOrderNo());
                orderUrl = format1+format;
            }
            orderExtInfo4.setExtValue(orderUrl);
            extInfo.add(orderExtInfo4);
            OrderExtInfo orderExtInfo5 = new OrderExtInfo();
            orderExtInfo5.setExtKey("tiny_app_id");

            orderExtInfo5.setExtValue(appId);
            extInfo.add(orderExtInfo5);
            OrderExtInfo orderExtInfo6 = new OrderExtInfo();
            orderExtInfo6.setExtKey("business_info");
            orderExtInfo6.setExtValue("{}");
            extInfo.add(orderExtInfo6);
            model.setExtInfo(extInfo);
            List<ItemOrderInfo> itemOrderList = new ArrayList<>();
            ItemOrderInfo itemOrderInfo = new ItemOrderInfo();
            itemOrderInfo.setItemName(productName);
            List<OrderExtInfo> extInfo2 = new ArrayList<>();
            OrderExtInfo orderExtInfo2 = new OrderExtInfo();
            orderExtInfo2.setExtKey("image_material_id");
            orderExtInfo2.setExtValue(materialId);
            extInfo2.add(orderExtInfo2);
            itemOrderInfo.setExtInfo(extInfo2);
            itemOrderList.add(itemOrderInfo);
            model.setItemOrderList(itemOrderList);
            //添加物流信息
            if ("IN_DELIVERY".equals(orderStatus)) {
                List<OrderLogisticsInformationRequest> logisticsInfoList = new ArrayList<>();
                OrderLogisticsInformationRequest logisticsInformation = new OrderLogisticsInformationRequest();
                log.info("物流订单号:{},物流公司:{}",ordersInfos.get(0).getExpressCompanyNo(),ordersInfos.get(0).getExpressNo());
                String alipayExpressCode = AlipayExpressEnum.getAlipayExpressCode(ordersInfos.get(0).getExpressCompanyNo());
                if (StringUtils.isBlank(alipayExpressCode)) {
                    alipayExpressCode = AlipayExpressEnum.getAlipayExpressCodeByName(ordersInfos.get(0).getExpressCompanyNo());
                }
                //设置默认值
                if (StringUtils.isBlank(alipayExpressCode)) {
                    alipayExpressCode = "POST";
                }

                logisticsInformation.setLogisticsCode(alipayExpressCode);
                logisticsInformation.setTrackingNo(ordersInfos.get(0).getExpressNo());
                logisticsInfoList.add(logisticsInformation);
                model.setLogisticsInfoList(logisticsInfoList);
            }

            syncRequest.setBizModel(model);
//            log.info("同步支付宝订单--->状态:{} 参数:{}",orderStatus, com.alibaba.fastjson.JSONObject.toJSONString(syncRequest));
            response = alipayClient.execute(syncRequest);
//            log.info("同步支付宝订单状态--->状态:{} 返回:{}",orderStatus, com.alibaba.fastjson.JSONObject.toJSONString(response));
        }catch (Exception e) {
            log.error("同步支付宝订单状态失败--->状态:{},错误信息:{}",orderStatus,e.getMessage());
            throw new ApiException("同步支付宝订单状态失败--->");
        }
        return response;
    }


    public String uploadImage(AlipayClient alipayClient,String image,Integer orderId){
        String materialId = joptsimple.internal.Strings.EMPTY;
        try{
            String imageBase64 = Base64Util.imageUrlToBase64(image);
            FileItem fileContent = new FileItem("fileContent.jpg", Base64.getDecoder().decode(imageBase64));
            AlipayMerchantItemFileUploadRequest request = new AlipayMerchantItemFileUploadRequest();
            request.setScene("SYNC_ORDER");
            request.setFileContent(fileContent);
//            log.info("下单上传图商品片到支付宝入参：{}", com.alibaba.fastjson.JSONObject.toJSONString(request));
            AlipayMerchantItemFileUploadResponse response = alipayClient.execute(request);
//            log.info("下单上传图商品片到支付宝返回：{}", com.alibaba.fastjson.JSONObject.toJSONString(response));
            if (response.isSuccess()) {
                materialId = response.getMaterialId();
//                redisService.set("ALIPAY_ORDER_SYNC_CREATE_" + orderId, materialId,60 * 60 * 24 * 30);
            }
        }catch (Exception e) {
            log.error("下单上传图商品片到支付宝失败! 原因:{}",e.getMessage());
            throw  new ApiException("下单上传图商品片到支付宝失败!");
        }
        return materialId;
    }

    /**
     * 刷新app_auth_token
     * @param appId
     * @return
     * @throws AlipayApiException
     */
    public CommonResult appAuthTokenByAppId(@RequestParam("appId") String appId) throws AlipayApiException {
        String appAuthCode = redisService.get(RedisConstants.APPAUTHCODE_KEY + appId);
        if (StringUtils.isEmpty(appAuthCode)) {
            log.info("===获取appAuthCode失败==={}", appId);
            throw new ApiException("获取AppAuthCode失败");
        }
        String refreshToken = redisService.get(RedisConstants.APPREFRESHTOKEN_KEY + appId);
        if (StringUtils.isEmpty(refreshToken)) {
            log.info("===获取refreshToken失败==={}", appId);
            throw new ApiException("获取AppRefreshAuthToken失败");
        }

        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");  //gateway:支付宝网关（固定）https://openapi.alipay.com/gateway.do
        certAlipayRequest.setAppId(alipayCertConstants.getAPPID());  //APPID 即创建应用后生成,详情见创建应用并获取 APPID
        certAlipayRequest.setPrivateKey(alipayCertConstants.getRSA_PRIVATE_KEY());  //开发者应用私钥，由开发者自己生成
        certAlipayRequest.setFormat("json");  //参数返回格式，只支持 json 格式
        certAlipayRequest.setCharset("UTF8");  //请求和签名使用的字符编码格式，支持 GBK和 UTF-8
        certAlipayRequest.setSignType(alipayConstants.getSIGNTYPE());  //商户生成签名字符串所使用的签名算法类型，目前支持 RSA2 和 RSA，推荐商家使用 RSA2。
        certAlipayRequest.setCertPath(alipayCertConstants.getAPP_CERT_PATH()); //应用公钥证书路径（app_cert_path 文件绝对路径）
        certAlipayRequest.setAlipayPublicCertPath(alipayCertConstants.getALIPAY_CERT_PATH()); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
        certAlipayRequest.setRootCertPath(alipayCertConstants.getALIPAY_ROOT_CERT_PATH());  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

        log.info("===alipay constants==={},{}", alipayConstants.getSIGNTYPE(), alipayCertConstants.getAPP_CERT_PATH());
        AlipayOpenAuthTokenAppRequest request = new AlipayOpenAuthTokenAppRequest();
        AlipayOpenAuthTokenAppModel model = new AlipayOpenAuthTokenAppModel();
        model.setGrantType("refresh_token");//换码类型 authorization_code：使用 auth_code 换取令牌；refresh_token：使用刷新刷新令牌
//        model.setCode(appAuthCode);//授权码 grant_type= authorization_code 时，必须录入
        model.setRefreshToken(refreshToken);//刷新令牌
        request.setBizModel(model);
        try {
            AlipayOpenAuthTokenAppResponse response = alipayClient.certificateExecute(request);
            log.info("===appAuthTokenByAppId response==={}", com.gexin.fastjson.JSONObject.toJSONString(response));
            String code = response.getCode();
            if (!"10000".equals(code)) {
                return CommonResult.failed();
            }
            List<AppTokenExchangeSubElement> tokens = response.getTokens();
            String appAuthToken_response = tokens.get(0).getAppAuthToken();
            String refreshToken_response = tokens.get(0).getAppRefreshToken();
            redisService.set(RedisConstants.APPAUTHTOKEN_KEY + appId, appAuthToken_response);
            redisService.expire(RedisConstants.APPAUTHTOKEN_KEY + appId, 364 * 24 * 60 * 60);//有效期364天
            redisService.set(RedisConstants.APPREFRESHTOKEN_KEY + appId, refreshToken_response);
            return CommonResult.success(appAuthToken_response);
        } catch (Exception e) {
            log.info("==={}===", e);
        }
        return CommonResult.failed();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String appPayOrder(AlipayOrderRequest request) {
        log.info("===appPayOrder==={}", request);
        Orders orders = ordersMapper.selectByPrimaryKey(request.getOrderId());
        if (IsPayConstant.YES.equals(orders.getIsPay())) {
            throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.PAID));
        }
        DefaultAddressDto address = null;
        if (null !=request.getAddressId()) {
            address = usersClient.getOneAddress(orders.getUserId(), request.getAddressId());
        }
        if (address == null) {
            address = new DefaultAddressDto();
            address.setProvince(orders.getProvince());
            address.setCity(orders.getCity());
            address.setArea(orders.getArea());
            address.setAddress(orders.getAddress());
            address.setTel(orders.getUserPhone());
            address.setName(orders.getUserName());
        }
        // 取出所有子订单
        List<OrdersInfo> ordersInfoList = ordersDao.getOrdersInfoList(request.getOrderId());
        // 取出第一条子订单
        OrdersInfo ordersInfo = ordersInfoList.get(0);

        try {
            // 获取生成的订单号
            String resOrderNo = OrderUtils.getPayOrderCode(orders.getUserId());
            boolean isSuccess=false;
            String result="";
            String tReqText="";

            AlipayTradeAppPayResponse response = new AlipayTradeAppPayResponse();
            //如果是支付宝小程序
            if(request.getIsJsApi()) {
                AlipayTradeCreateRequest tradeCreateRequest = new AlipayTradeCreateRequest();
                AlipayTradeCreateModel model = new AlipayTradeCreateModel();
                String productName = ordersInfo.getProductName().trim().replaceAll("%","");
                if (productName.length() > 30) {
                    productName = productName.substring(0, 20);
                }
                model.setBody("XXXX优品小程序");
                model.setSubject(productName);
                model.setOutTradeNo(resOrderNo);
                if (request.getAlipayUserId() == null) {
                    throw new ApiException("下单失败，支付宝用户id缺失");
                }
                model.setBuyerId(request.getAlipayUserId());
                model.setTotalAmount(String.valueOf(orders.getRealTotalMoney()));
                tradeCreateRequest.setNotifyUrl(alipayConstants.getNOTIFY_URL());
                if (StringUtils.isNotBlank(request.getBackUrl())) {
                    tradeCreateRequest.setReturnUrl(request.getBackUrl() + "?orderId=" + request.getOrderId() + "&sourcePlatform="+request.getSourcePlatform());
                }
                com.alibaba.fastjson.JSONObject bizContent = new  com.alibaba.fastjson.JSONObject();


                bizContent.put("out_trade_no", resOrderNo);
                bizContent.put("total_amount", String.valueOf(orders.getRealTotalMoney()));
                bizContent.put("subject", productName);
                bizContent.put("buyer_id", request.getAlipayUserId());

                // 商品明细信息，按需传入
                JSONArray goodsDetail = new JSONArray();
                com.alibaba.fastjson.JSONObject goods1 = new  com.alibaba.fastjson.JSONObject();
                goods1.put("goods_id", ordersInfo.getProductId().toString());
                goods1.put("goods_name", ordersInfo.getProductName());
                goods1.put("quantity", ordersInfo.getProductSum().longValue());
                goods1.put("price", ordersInfo.getProductPrice().toString());
                goodsDetail.add(goods1);
                bizContent.put("goods_detail", goodsDetail);
                tradeCreateRequest.setBizContent(bizContent.toString());

                tradeCreateRequest.setBizModel(model);

                com.alibaba.fastjson.JSONObject syncBizContent = new  com.alibaba.fastjson.JSONObject();
                syncBizContent.put("amount",String.valueOf(orders.getRealTotalMoney()));

                AlipayTradeCreateResponse alipayTradeCreateResponse = jsapiSdkExecute(tradeCreateRequest,request.getChildId()).getData();
                BeanUtil.copyProperties(alipayTradeCreateResponse,response);
                isSuccess = response != null && response.isSuccess();
                if (isSuccess) {
                    result = response.getTradeNo();
                }

            } else {
                response = alipayMobile(resOrderNo,orders.getRealTotalMoney(),"XXXX优品商城","",request.getChildId());
                isSuccess = response != null && response.isSuccess();
                if (isSuccess) {
                    result = response.getBody();
                }

            }

            OrdersPay pay = new OrdersPay();
            pay.setAmount(orders.getRealTotalMoney());
            pay.setOrderNo(orders.getOrderNo());
            pay.setResOrderNo(resOrderNo);
            pay.setPayType(PayPayTypeEnums.BEING_PROCESSED.getType());
            if(request.getIsJsApi()){
                //支付宝小程序
                pay.setTradeType("aliPay-jsApi");
            }else{
                //支付宝app
                pay.setTradeType("aliPay");
            }
            pay.setChildId(request.getChildId());
            pay.setCreateTime(new Date());
            ordersPayMapper.insertSelective(pay);

            if (response.isSuccess()) {
                orders.setProvince(address.getProvince());
                orders.setCity(address.getCity());
                orders.setArea(address.getArea());
                orders.setAddress(address.getAddress());
                orders.setUserAddress(address.getProvince() + address.getCity() + address.getArea() + address.getAddress());
                orders.setUserName(address.getName());
                orders.setUserPhone(address.getTel());
                orders.setIsAnonymity(request.getIsAnonymity());
                orders.setOrderRemarks(request.getDesc());
                orders.setOrderSource(request.getSourcePlatform());
                orders.setRealNameId(request.getRealNameId());
                ordersMapper.updateByPrimaryKeySelective(orders);
                try {
                    OrdersExample ordersExample = new OrdersExample();
                    ordersExample.createCriteria().andOrderNoEqualTo(orders.getOrderNo());
                    List<Orders> ordersList = ordersMapper.selectByExample(ordersExample);
                    ordersService.subStock(request.getOrderId());
                    if (orderPushSwitch) {
                        if (!CollectionUtils.isEmpty(ordersList)){
                            log.info("上传供应链4============{}",request.getOrderId());
                            ordersService.ordersUpload(request.getOrderId(),null);
                        }
                    }
                } catch (Exception e) {
                    log.info("上传供应链4失败============{},{}",request.getOrderId(),e);
                }
                return result;
            } else {
                throw new ApiException(JSON.toJSONString(response));
            }
        } catch (Exception e) {
            log.error("支付宝支付异常，{}",e);
            if (e.getMessage()!=null && !e.getMessage().contains("买家认证不通过，无法继续交易") && !e.getMessage().contains("Duplicate entry")){
                FeiShuUtil.sendMsg(String.format("appPayOrder接口异常,%s",e.getMessage()));
            }
        }
        return "";
    }

    @Override
    public Boolean judgeRegionList(FreightTemplateResponse freightTemplateResponse, FreightTemplateResponse chainFreightTemplate, String city) {
        List<String> regionList = Lists.newArrayList();
        if(freightTemplateResponse != null) {
            YxAstrictRegionResponse astrictRegion = freightTemplateResponse.getAstrictRegion();
            if (null != astrictRegion && StringUtils.isNotBlank(astrictRegion.getRegion())) {
                List<String> regions = Arrays.asList(astrictRegion.getRegion().split(","));
                regionList.addAll(regions);
            }
        }
        if(chainFreightTemplate !=null) {
            YxAstrictRegionResponse chainRegion = chainFreightTemplate.getAstrictRegion();
            if (null != chainRegion && StringUtils.isNotBlank(chainRegion.getRegion())) {
                List<String> chainRegions = Arrays.asList(chainRegion.getRegion().split(","));
                regionList.addAll(chainRegions);
            }
        }
        if(!CollectionUtils.isEmpty(regionList)) {
            if( regionList.contains(city)) {
                return false;
            }
        }
        return true;
    }

    @Transactional
    public boolean updateGoupBuyUserRelStatus(String orderNo, Integer status) {
        return groupActivityService.updateGoupBuyUserRelStatus(orderNo, status);
    }

    private void doSubSubsidy(Orders orders, String platformData) {
        List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectOrderInfoByOrderId(orders.getId());
        // 删除补贴价格
        ordersInfoList.stream()
                .forEach(item -> {
                    // 扣除补贴价格
                    if ("OLD_FOR_NEW".equals(item.getActivityType())) {
                        String key = RedisConstants.SUBSIDYKEY_APP + orders.getH5Token();
                        if ("APP".equals(platformData.toUpperCase())) {
                            this.addUsedSubsidy(item, RedisConstants.RECORD_SUBSIDYKEY_APP + orders.getH5Token(), orders.getUserId());
                        }else {
                            String subsidyObj = redisService.getMapString(key, item.getProductId().toString());
                            if (org.apache.commons.lang3.StringUtils.isNotEmpty(subsidyObj)) {
                                redisService.delete(key, item.getProductId().toString());
                                this.addUsedSubsidy(item, RedisConstants.RECORD_SUBSIDYKEY_APP + orders.getH5Token());
                            }
                        }
                    }
//                            // 扣除用户的红包余额
//                            if ("CASH_COUPON".equals(item.getActivityType())) {
//                                //记录用户使用红包金额
//                                this.addUsedActivityMax(item.getActivityMax(), RedisConstants.RETURN_COUPON_APP + orders.getH5Token());//记录用户使用红包金额
//                            }
//                            //
//                            if ("RETURN_COUPON".equals(item.getActivityType())) {
//                                this.addReturnCoupon(item.getActivityMax(), RedisConstants.RETURN_COUPON_APP + orders.getH5Token());//记录用户返现红包金额
//                            }
                });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String quickAppPay(AlipayOrderRequest request) {
        Orders orders = ordersMapper.selectByPrimaryKey(request.getOrderId());
        if (IsPayConstant.YES.equals(orders.getIsPay())) {
            throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.PAID));
        }
        try {
            AlipayClient alipayClient = alipayUtil.getAlipayClient(null);
            AlipayTradeAppPayRequest AppRequest = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setBody("XXXX优品");
            model.setSubject("XXXX优品");
            // 获取生成的订单号
            String resOrderNo = OrderUtils.getPayOrderCode(orders.getUserId());
            model.setOutTradeNo(resOrderNo);
            model.setTotalAmount(String.valueOf(orders.getRealTotalMoney()));
            AppRequest.setNotifyUrl(alipayConstants.getNOTIFY_URL());
            AppRequest.setBizModel(model);
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(AppRequest);
            if (response.isSuccess()) {
                OrdersPay pay = new OrdersPay();
                pay.setAmount(orders.getRealTotalMoney());
                pay.setOrderNo(orders.getOrderNo());
                pay.setResOrderNo(resOrderNo);
                pay.setPayType(PayPayTypeEnums.BEING_PROCESSED.getType());
                pay.setTradeType("aliPay");
                pay.setCreateTime(new Date());
                ordersPayMapper.insertSelective(pay);
                orders.setOrderRemarks(request.getDesc());
                ordersMapper.updateByPrimaryKeySelective(orders);
                return response.getBody();
            } else {
                throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.ZFB_CREATES_ORDER_ERROR));
            }
        } catch (AlipayApiException e) {
            log.error("支付宝支付异常!");
            e.printStackTrace();
        }
        return "";
    }


    /**
     * 第一步:验证签名,签名通过后进行第二步
     * 第二步:按以下步骤进行验证
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
     * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
     * 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方
     * （有的时候，一个商户可能有多个seller_id/seller_email），
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
     * 支付宝回调
     */
    @Override
    public String callback(HttpServletRequest request,String tradeType,String childId) {
        // 将异步通知中收到的待验证所有参数都存放到map中
        Map<String, String> params = convertRequestParamsToMap(request);
        String paramsJson = JSON.toJSONString(params);
        log.info("支付宝回调 {}", paramsJson);
        try {
            // 调用SDK验证签名
            boolean signVerified ;
            String appId =Strings.EMPTY;
            //支付宝小程序回调
            if (StringUtils.isNotBlank(tradeType) && ("aliPay-jsApi".equals(tradeType) ||"aliPay".equals(tradeType) )) {
                if (StringUtils.isNotBlank(childId) && "1".equals(childId)) {
                    signVerified = AlipaySignature.rsaCheckV1(params, alipayConstants.getCHILD_JSAPI_ALIPAY_PUBLIC_KEY(), "utf-8", "RSA2");
                    appId = alipayConstants.getCHILD_JSAPI_APPID();
                } else if (StringUtils.isNotBlank(childId) && "APP_1".equals(childId)) {
                    signVerified = AlipaySignature.rsaCheckV1(params, alipayConstants.getAPP_ALIPAY_PUBLIC_KEY(), alipayConstants.getCHARSET(), alipayConstants.getSIGNTYPE());
                    appId = alipayConstants.getAPP_APPID();
                } else {
                    signVerified = AlipaySignature.rsaCheckV1(params, alipayConstants.getJSAPI_ALIPAY_PUBLIC_KEY(), "utf-8", "RSA2");
                    appId = alipayConstants.getJSAPI_APPID();
                }

            } else {
                signVerified  = AlipaySignature.rsaCertCheckV1(params, alipayCertConstants.getALIPAY_CERT_PATH(),
                        alipayConstants.getCHARSET(), alipayConstants.getSIGNTYPE());
            }

            if (signVerified) {
                log.info("支付宝回调签名认证成功");
                // 按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，
                // 校验成功后在response中返回success，校验失败返回failure
                this.check(params);
                // 开始处理业务
                AlipayNotifyResponse param = buildAlipayNotifyParam(params);
                String trade_status = param.getTradeStatus();
                // 支付成功
                if (trade_status.equals(AlipayTradeConstant.TRADE_SUCCESS) || trade_status.equals(AlipayTradeConstant.TRADE_FINISHED)) {
                    try {
                        // 处理业务逻辑
                        this.handleOrderInfo(params,tradeType,appId,childId);
                    } catch (Exception e) {
                        log.error("支付宝回调业务处理报错,params:" + paramsJson, e);
                    }
                    return "success";
                }
            }
            log.info("支付宝回调签名认证失败，signVerified=false, paramsJson:{}", paramsJson);
            return "failure";
        } catch (AlipayApiException e) {
            log.error("支付宝回调签名认证失败,paramsJson:{},errorMsg:{}", paramsJson, e.getMessage());
        }
        return "failure";
    }

    @Override
    public String h5CallBack(HttpServletRequest request, HttpServletResponse response) {
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            params.put(name, valueStr);
        }
        String paramsJson = JSON.toJSONString(params);
        Map<String, String> paramsCopy = new HashMap<>(params);
        log.info("支付宝回调 {}", paramsJson);

        try {
            //计算得出通知验证结果
            boolean verifyResult = false;

            // 按照支付结果异步通知中的描述，对支付结果中的业务内容进行校验，
            verifyResult = this.check(params);

            //验证成功
            if (verifyResult) {
                log.info("支付宝回调签名认证成功");

                // 开始处理业务
                AlipayNotifyResponse param = buildAlipayNotifyParam(params);
                String trade_status = param.getTradeStatus();
                // 支付成功
                if (trade_status.equals(AlipayTradeConstant.TRADE_SUCCESS) || trade_status.equals(AlipayTradeConstant.TRADE_FINISHED)) {
                    //处理成功之支付逻辑
                    try {
                        // 处理业务逻辑
                        this.handleOrderInfoV2(params);
                    } catch (Exception e) {
                        log.error("支付宝回调业务处理报错,params:" + paramsJson);
                        log.error("==={}===", e);
                    }
                } else {
                    log.error("没有处理支付宝回调业务，支付宝交易状态：{},params:{}", trade_status, paramsJson);
                }
                // 如果签名验证正确，立即返回success，后续业务另起线程单独处理
                // 业务处理失败，可查看日志进行补偿，跟支付宝已经没多大关系。
                return "success";
            }
            log.info("支付宝回调签名认证失败，signVerified=false, paramsJson:{}", paramsJson);
            return "failure";

        } catch (AlipayApiException e) {
            log.error("支付宝回调签名认证失败,paramsJson:{},errorMsg:{}", paramsJson, e.getMessage());
        }
        return "failure";
    }

    /**
     * APP支付宝回调后处理业务逻辑
     */
    private void handleOrderInfo(Map<String, String> map,String tradeType,String appId,String childId) {
        // 查询订单是否是处理中
        String resOrderNo = map.get("out_trade_no");
        log.debug("订单编号: {}", resOrderNo);
        OrdersPay pay = ordersDao.queryOrdersPayByResOrderNo(resOrderNo);
        if (null == pay || (!pay.getPayType().equals(PayPayTypeEnums.BEING_PROCESSED.getType()) && PayPayTypeEnums.FAIL.getType() != pay.getPayType().byteValue())) {
            return;
        }
        // 更新支付订单信息
        pay.setTradeType("aliPay");
        pay.setTotalFee(new BigDecimal(map.get("total_amount")).multiply(new BigDecimal(100)).setScale(0).intValue());
        pay.setResText(com.alibaba.fastjson.JSONObject.toJSONString(map));
        pay.setPayTime(map.get("gmt_payment"));
        pay.setPayType(PayPayTypeEnums.SUCCEED.getType());
        pay.setUpdateTime(new Date());
        ordersPayMapper.updateByPrimaryKeySelective(pay);
        // 更新订单信息
        Orders orders = new Orders();
        orders.setPayType(OrderPayTypeEnums.online_pay.name());
        orders.setPaySource(OrderPaySource.alipay.name());
        orders.setIsPay(IsPayConstant.YES);
        orders.setOrderStatus(OrderStatusEnums.UNSHIPPED.getValue());
        orders.setPayTime(new Date());
        orders.setTradeNo(pay.getResOrderNo());
        OrdersExample example = new OrdersExample();
        example.createCriteria().andOrderNoEqualTo(pay.getOrderNo());
        ordersMapper.updateByExampleSelective(orders, example);

        // 获取订单信息
        Orders order = ordersDao.queryOrdersByOrderNo(pay.getOrderNo());
        orders.setUserId(order.getUserId());
        try {
            BigDecimal money = usersClient.getMoney(orders.getUserId());
            log.info("===用户账户余额==={}, {}", money, order.getDeductionMoney());
            if (order.getDeductionMoney() != null && order.getDeductionMoney().compareTo(null == money ? BigDecimal.ZERO : money) > 0) {
                log.error("===账户余额不足，支付失败==={}", order.getOrderNo());

                OrdersInfoExample ordersInfoExample = new OrdersInfoExample();
                ordersInfoExample.createCriteria().andOrderIdEqualTo(order.getId());
                List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectByExample(ordersInfoExample);
                ordersInfoList.stream()
                        .forEach(item -> {
                            OrdersInfo ordersInfo = new OrdersInfo();
                            ordersInfo.setId(item.getId());
                            ordersInfo.setOrderinfoStatus(OrderStatusEnums.LOSE_EFFICACY.getValue());
                            ordersInfoMapper.updateByPrimaryKeySelective(ordersInfo);
                        });
                order.setOrderStatus(OrderStatusEnums.LOSE_EFFICACY.getValue());
                order.setSmallNote("订单已支付，但是余额不足！");
                ordersMapper.updateOrderStatus(order.getId(), Integer.parseInt(OrderStatusEnums.LOSE_EFFICACY.getValue()));
                return;
            }
        } catch (Exception e) {
            log.error("===支付宝回调校验用户余额异常==={}", e);
        }

        if(order.getDeductionMoney() != null && order.getDeductionMoney().doubleValue() > 0d) {
            UserBalanceDto userBalanceDto = new UserBalanceDto();
            userBalanceDto.setUserId(orders.getUserId());
            userBalanceDto.setUpdateMoney(order.getDeductionMoney());
            userBalanceDto.setType("SUB");
            userBalanceDto.setSource(UserBalanceSourceEnums.DEDUCTION.name());
            userBalanceDto.setAmountType(1);
            userBalanceDto.setCode(orders.getOrderNo());
            usersClient.updateMoney(userBalanceDto);
        }

        // 获取订单明细
        OrdersInfoExample ordersInfoExample = new OrdersInfoExample();
        ordersInfoExample.createCriteria().andOrderIdEqualTo(order.getId());
        List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectByExample(ordersInfoExample);
        ordersInfoList.stream()
                .forEach(item -> {
                    // 修改订单详情状态
                    OrdersInfo ordersInfo = new OrdersInfo();
                    ordersInfo.setId(item.getId());
                    ordersInfo.setOrderinfoStatus(OrderStatusEnums.UNSHIPPED.getValue());
                    ordersInfoMapper.updateByPrimaryKeySelective(ordersInfo);

                    // 商品 减库存 加销量 店家加销量
                    productService.sellAfter(item.getProductId(), item.getProductSpecId(), item.getProductSum(), item.getProductPrice(),
                                item.getIsWalletPay(), item.getIsDirectbuy(), item.getActivityType(), item.getActivityMax(), order.getUserId());
                    // 删除补贴价格
                    if ("OLD_FOR_NEW".equals(item.getActivityType())) {
                        String key = RedisConstants.SUBSIDYKEY_APP + order.getH5Token();
                        log.info("===支付宝支付回调，获取当前platformData={}=,orderSource={}==", TokenUtil.getPlatformData(), order.getOrderSource());
//                        if ("APP".equals(TokenUtil.getPlatformData().toUpperCase())) {
                            this.addUsedSubsidy(item, RedisConstants.RECORD_SUBSIDYKEY_APP + order.getH5Token(), order.getUserId());//因为支付回调无法区分开是app还是h5 所以默认保存一次app的数据
//                        }else {
                            String subsidyObj = "";
                            try {
                                subsidyObj = redisService.getMapString(key, item.getProductId().toString());
                            } catch (Exception e) {
                                log.info("===redis get key is err===");
                            }
                            if (org.apache.commons.lang3.StringUtils.isNotEmpty(subsidyObj)) {
                                redisService.delete(key, item.getProductId().toString());
                                this.addUsedSubsidy(item, RedisConstants.RECORD_SUBSIDYKEY_APP + order.getH5Token());
                            }
//                        }
                    }
                    // 扣除用户的红包余额
                    if ("CASH_COUPON".equals(item.getActivityType())) {
                        //记录用户使用红包金额
                        this.addUsedActivityMax(item.getActivityMax(), RedisConstants.RETURN_COUPON_APP + order.getH5Token());//记录用户使用红包金额
                    }
                    //
                    if ("RETURN_COUPON".equals(item.getActivityType())) {
                        this.addReturnCoupon(item.getActivityMax(), RedisConstants.RETURN_COUPON_APP + order.getH5Token());//记录用户返现红包金额
                    }
                });

        //暂时注释试试 防止用户未点支付成功页面的完成
        Orders waitMatchOrders = null;
        try{
            waitMatchOrders = ordersDao.queryOrdersByOrderNo(pay.getOrderNo());
            log.info("===处理拼团判断订单状态==={}", waitMatchOrders.getOrderStatus());
            if (OrderStatusEnums.UNSHIPPED.getValue().equals(waitMatchOrders.getOrderStatus())) {
                ordersService.updateGoupBuyUserRelStatus(order.getOrderNo(), 1);
            }
        } catch (Exception e) {
            log.info("===支付完成后更新yx_group_buy_user_rel表状态异常==={}", e);
        }

        try {
            Integer orderInfoId = ordersInfoMapper.selectorderId(orders.getOrderNo());
            helpWorkInfoDao.updateStatu(orderInfoId);
        } catch (Exception e) {
            log.info("===e==={}", e);
            log.error("===支付完成后更新助力单状态异常==={}", orders);
        }
//        try {
//            log.info("===支付宝回调测评订单赠送佣金开始==={}", order.getOrderNo());
//            //如果订单是从测评进入的，则赠送测评用户佣金
//            if (null == waitMatchOrders) {
//                waitMatchOrders = ordersDao.queryOrdersByOrderNo(pay.getOrderNo());
//            }
//            log.info("===支付宝回调测评订单赠送佣金判断订单状态==={}", waitMatchOrders.getOrderStatus());
//            if (OrderStatusEnums.UNSHIPPED.getValue().equals(waitMatchOrders.getOrderStatus())) {
//                giveBrokerageByDynamic(order.getOrderNo());
//            }
//            log.info("===支付宝回调测评订单赠送佣金结束==={}", order.getOrderNo());
//        } catch (Exception e) {
//            log.info("===支付宝回调测评订单赠送佣金失败==={}", e);
//        }
        //发短信
        sendOrderPaySucSms(order, ordersInfoList.get(0), ordersInfoList.size());
        try {
            ordersService.subStock(order.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (orderPushSwitch) {
            try {
                log.info("上传供应链5============{}",order.getId());
                ordersService.ordersUpload(order.getId(),null);

            } catch (Exception e) {
                log.error("上传供应链5失败============{},{}",order.getId(),e);
            }
        }

        //同步支付宝订单信息
        try{
            if ("aliPay-jsApi".equals(tradeType)) {
                syncAliPayOrder("PAID", order.getOrderNo(), order.getId().toString(), orders.getUserId(), ordersInfoList.get(0).getProductName(), order.getCreateTime(), childId, ordersInfoList.get(0).getProductImg());
            }
        }catch (Exception e) {
            log.error("同步支付宝订单状态失败PAID-->到支付宝失败:{}",e.getMessage());
        }
        //用户支付订单数据预警
        try{
            //测试排除
            if (!order.getTel().equals("17388585858") && !order.getUserName().contains("测试")){
                Integer orderNum = ordersMapper.queryUserPaySuccessOrderNum(order.getTel(), 1);
                if (orderNum>=checkOrderNum) {
                    FeiShuUtil.sendOrderNumMsg(PlatformEnum.getPlatformName(ordersInfoList.get(0).getChildOrderNo().substring(0,1))
                            +"       "+order.getTel()+order.getUserName()+"已支付"+ orderNum +"笔 请检查!");
                }
            }
        }catch (Exception e) {
            log.error("查询用户支付订单数据预警失败:{}",e.getMessage());
        }

    }

    /**
     * 赠送测评佣金
     * @param orderNo
     */
    private void giveBrokerageByDynamic(String orderNo) {
        if (StringUtils.isEmpty(orderNo)) {
            return;
        }
        Orders orders = ordersDao.queryOrdersByOrderNo(orderNo);
        if (null == orders) {
            return;
        }
        Integer dynamicId = orders.getDynamicId();
        if (null == dynamicId) {
            return;
        }
        Dynamic dynamic = dynamicMapper.selectByPrimaryKey(dynamicId);
        if (dynamic == null) {
            return;
        }
        if (null == dynamic.getIsReason()) {
            dynamic.setIsReason((byte)1);
        }
        if (0 == dynamic.getIsReason() || 1 != dynamic.getStatus()) {
            return;
        }
        if (ActivityTypeEnums.ZERO_EVALUATION.name().equals(dynamic.getActivityType())) {
            return;
        }
        BigDecimal productPrice = dynamic.getProdcutPrice();//商品售价
        BigDecimal brokerage = productPrice.multiply(new BigDecimal(brokerageRatio)).setScale(4, RoundingMode.HALF_UP).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        usersClient.addBalance(brokerage, dynamic.getUserId(), UserBalanceSourceEnums.EVALUATION_COMMISSION.name());
    }

    /**
     * H5支付宝回调后处理业务逻辑
     */
    private void handleOrderInfoV2(Map<String, String> map) {
        // 查询订单是否是处理中
        String resOrderNo = map.get("out_trade_no");
        log.info("订单编号: {}", resOrderNo);
        OrdersPay pay = ordersDao.queryOrdersPayByResOrderNo(resOrderNo);
        if (null == pay || pay.getPayType().equals(PayPayTypeEnums.SUCCEED.getType())) {//|| !pay.getPayType().equals(PayPayTypeEnums.BEING_PROCESSED.getType()) 去掉这个是因为
            return;
        }
        // 更新支付订单信息
        pay.setTradeType("aliPay");
        pay.setTotalFee(new BigDecimal(map.get("total_amount")).multiply(new BigDecimal(100)).setScale(0).intValue());
        pay.setResText(com.alibaba.fastjson.JSONObject.toJSONString(map));
        pay.setPayTime(map.get("gmt_payment"));
        pay.setPayType(PayPayTypeEnums.SUCCEED.getType());
        pay.setUpdateTime(new Date());
        ordersPayMapper.updateByPrimaryKeySelective(pay);
        // 更新订单信息
        Orders orders = new Orders();
        orders.setPayType(OrderPayTypeEnums.online_pay.name());
        orders.setPaySource(OrderPaySource.alipay.name());
        orders.setIsPay(IsPayConstant.YES);
        orders.setOrderStatus(OrderStatusEnums.UNSHIPPED.getValue());
        orders.setPayTime(new Date());
        orders.setTradeNo(pay.getResOrderNo());
        try {
            String seller_email = map.get("seller_email");
            orders.setAccount(seller_email);
        } catch (Exception e) {
            log.error("{}",e);
        }
        OrdersExample example = new OrdersExample();
        example.createCriteria()
                .andOrderNoEqualTo(pay.getOrderNo());
        ordersMapper.updateByExampleSelective(orders, example);

        // 获取订单信息
        Orders order = ordersDao.queryOrdersByOrderNo(pay.getOrderNo());

        // 获取订单明细
        OrdersInfoExample ordersInfoExample = new OrdersInfoExample();
        ordersInfoExample.createCriteria()
                .andOrderIdEqualTo(order.getId());
        List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectByExample(ordersInfoExample);
        ordersInfoList.stream()
                .forEach(item -> {
                    OrdersInfo ordersInfo = new OrdersInfo();
                    ordersInfo.setId(item.getId());
                    ordersInfo.setOrderinfoStatus(OrderStatusEnums.UNSHIPPED.getValue());
                    ordersInfoMapper.updateByPrimaryKeySelective(ordersInfo);
                    String tokenUser = redisService.get(order.getH5Token());
                    try {
                        // 商品 减库存 加销量 店家加销量
                        productService.sellAfter(item.getProductId(), item.getProductSpecId(), item.getProductSum(), item.getProductPrice(),
                                item.getIsWalletPay(), tokenUser, item.getIsDirectbuy(), item.getActivityType(), item.getActivityMax(), order.getUserId());
                    } catch (Exception e) {
                        log.error("程序出现异常：e:{}", GlobalExceptionHandler.getExceptionToString(e));
                        log.error("减库存发生异常 订单id :{}", item.getId());
                    }

                    switch (item.getActivityType()) {
                        case "RETURN_COUPON":// 增加用户的红包返现余额
                            this.addReturnCoupon(item.getActivityMax(), RedisConstants.RETURN_COUPON + order.getH5Token());//记录用户返现红包金额
                            break;
                        case "CASH_COUPON":// 扣除用户的红包余额
                            this.addUsedActivityMax(item.getActivityMax(), RedisConstants.RETURN_COUPON + order.getH5Token());//记录用户使用红包金额
                            break;
                        case "OLD_FOR_NEW":// 删除补贴价格
                            String key = RedisConstants.SUBSIDYKEY + order.getH5Token();
                            String subsidyObj = redisService.getMapString(key, item.getProductId().toString());
                            if (org.apache.commons.lang3.StringUtils.isNotEmpty(subsidyObj)) {
                                redisService.delete(key, item.getProductId().toString());
                                this.addUsedSubsidy(item, RedisConstants.RECORD_SUBSIDYKEY + order.getH5Token());
                            }
                            break;
                        case "SHOPPING_CARNIVAL":
                            if(item.getActivityMax()!=null) {
                                addH5Score(item.getActivityMax().intValue(), order.getH5Token());
                            }
                            break;
                    }

                });
        // 发送短信
//        SendMsg.sendOrderInfo(order.getUserPhone());
        try {
            sendOrderPaySucSms(order, ordersInfoList.get(0), ordersInfoList.size());
        } catch (Exception e) {
            e.printStackTrace();
        }

        OrdersExample ordersExample = new OrdersExample();
        ordersExample.createCriteria().andOrderNoEqualTo(pay.getOrderNo());
        List<Orders> ordersList = ordersMapper.selectByExample(ordersExample);
        try {
            ordersService.subStock(ordersList.get(0).getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (orderPushSwitch) {
            try {
                if (!CollectionUtils.isEmpty(ordersList)) {
                    log.info("上传供应链6============{}", ordersList.get(0).getId());
                    ordersService.ordersUpload(ordersList.get(0).getId(),null);
                }
            } catch (Exception e) {
                log.info("上传供应链6失败============{}", e);
            }
        }

        //用户支付订单数据预警
        try{
            //测试排除
            if (!order.getTel().equals("17388585858") && !order.getUserName().contains("测试")){
                Integer orderNum = ordersMapper.queryUserPaySuccessOrderNum(order.getTel(), 1);
                if (orderNum>=checkOrderNum) {
                    FeiShuUtil.sendOrderNumMsg(PlatformEnum.getPlatformName(ordersInfoList.get(0).getChildOrderNo().substring(0,1))
                            +"       "+order.getTel()+order.getUserName()+"已支付"+ orderNum +"笔 请检查!");
                }
            }
        }catch (Exception e) {
            log.error("查询用户支付订单数据预警失败:{}",e.getMessage());
        }

        //推送支付订单数据到阿里云
        new Thread(()->{
            try {
                AliyunMallRequest aliyunMallRequest = new AliyunMallRequest();
                aliyunMallRequest.setBatchName("");
                aliyunMallRequest.setChannelCode(order.getChannel());
                aliyunMallRequest.setOrderTime(DateTimeUtil.TimeToStr(order.getCreateTime()));
                aliyunMallRequest.setProvince(order.getProvince());
                aliyunMallRequest.setStatus("2");
                aliyunMallRequest.setOrderNo(ordersInfoList.get(0).getChildOrderNo());
                aliyunMallRequest.setPhone(order.getTel());
                aliyunMallRequest.setPaymentAmount(order.getRealTotalMoney().toString());
                aliyunMallRequest.setName(order.getUserName());
                aliyunMallRequest.setCost(ordersInfoList.get(0).getCostPrice().toString());
                AliyunMallApiUtil.orderPush(aliyunMallRequest);
            } catch (Exception e) {
                log.error("支付订单推送阿里云失败", e);
            }
        }).start();



        //推送百度事件信息
//        try{
//            String h5Token = order.getH5Token();
//            new Thread(()->{
//                String usesInfo = redisService.get(h5Token);
//                String a_oId = "";
//                if (StringUtils.isNotBlank(usesInfo)) {
//                    UsersResponse usersResponse = com.alibaba.fastjson.JSONObject.parseObject(usesInfo, UsersResponse.class);
//                    if (StringUtils.isNotBlank(usersResponse.getAoId())) {
//                        a_oId =  usersResponse.getAoId();
//                    }
//                }
//                if(StringUtils.isNotBlank(a_oId)){
//                    List<ConversionType> conversionTypes = new ArrayList<>();
//                    // 编辑一条转化数据
//                    ConversionType cv = new ConversionType();
//                    cv.setLogidUrl(a_oId); // 设置落地页url
//                    cv.setNewType(90); // 设置转化类型
//                    cv.setConvertTime(System.currentTimeMillis() / 1000);
//                    conversionTypes.add(cv);
//                    BaiduApiUtil.sendConvertData(baiduToken, conversionTypes);
//                }
//            }).start();
//        }catch (Exception e) {
//            log.error("推送到百度事件信息错误:{}",e.getMessage());
//        }
    }

    private void sendOrderPaySucSms(Orders orders, OrdersInfo ordersInfo, int size) {
        // 发送短信
        try {
            log.info("===cmpp下单成功发送短信手机号==={}", orders.getUserPhone());
            SmsDto smsDto = new SmsDto();
            smsDto.setPhone(orders.getUserPhone());
            smsDto.setType(2);
            String productName = ordersInfo.getProductName();
            if (size > 1) {
                if (productName.length() > 12) {
                    productName = productName.substring(0, 12) + "-";
                } else {
                    productName = productName + "-";
                }
            } else {
                if (productName.length() > 12) {
                    productName = productName.substring(0, 12) + "-";
                }
            }
            smsDto.setCode(productName);
            smsDto.setOrderSource(orders.getOrderSource());
            smsDto.setChannel(orders.getChannel());
            smsDto.setDomainUrl(orders.getDomainUrl());
            smsDto.setOrderId(orders.getId());
            smsDto.setToken(orders.getH5Token());
            rabbitTemplate.convertAndSend(QueueConstants.SMS_QUEUE, smsDto);

        } catch (Exception e) {
            log.error("alipay下单成功发送短信失败,{}",e);
        }
    }

    //返积分
    private void addH5Score(Integer addScore,String h5token){
        try {
            String usesInfo = redisService.get(h5token);
            UsersResponse usersResponse = com.alibaba.fastjson.JSONObject.parseObject(usesInfo, UsersResponse.class);
            usersResponse.setScore(usersResponse.getScore() + addScore);
            redisService.set(usersResponse.getToken(), com.alibaba.fastjson.JSONObject.toJSONString(usersResponse));
            redisService.expire(usersResponse.getToken(), TokenConstants.EXPIRE_SECONDS);
        } catch (Exception e) {
            log.error("加积分异常：h5token={}", h5token);
        }

    }
    private void addReturnCoupon(BigDecimal ordersInfoActivityMax, String key) {
        ReturnCouponResponse returnCouponResponse = new ReturnCouponResponse();
        // 商品红包
        ordersInfoActivityMax = Optional.ofNullable(ordersInfoActivityMax)
                .orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);

        if (StringUtils.isNotEmpty(redisService.get(key))) {// 记录用户返现红包金额
            returnCouponResponse = com.alibaba.fastjson.JSONObject.parseObject(redisService.get(key), ReturnCouponResponse.class);
            // 累计返现红包
            BigDecimal totalReturnCoupon = Optional.ofNullable(returnCouponResponse.getTotalReturnCoupon())
                    .orElse(BigDecimal.ZERO);

            returnCouponResponse.setTotalReturnCoupon(totalReturnCoupon
                    .add(ordersInfoActivityMax)
                    .setScale(2, BigDecimal.ROUND_HALF_UP));

            // 返现红包加入用户的红包中
            BigDecimal userActivityMax = Optional.ofNullable(returnCouponResponse.getActivityMax()).orElse(BigDecimal.ZERO);

            returnCouponResponse.setActivityMax(
                    ordersInfoActivityMax
                            .add(userActivityMax)
                            .setScale(2, BigDecimal.ROUND_HALF_UP));
        } else {
            returnCouponResponse.setActivityMax(
                    ordersInfoActivityMax
                            .add(new BigDecimal(680))
                            .setScale(2, BigDecimal.ROUND_HALF_UP));

            returnCouponResponse.setTotalReturnCoupon(Optional.ofNullable(ordersInfoActivityMax)
                    .orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP));
            returnCouponResponse.setUsedActivityMax(BigDecimal.ZERO);
        }
        redisService.set(key, com.alibaba.fastjson.JSONObject.toJSONString(returnCouponResponse));
        redisService.expire(key, TokenConstants.EXPIRE_SECONDS);
    }

    private void addUsedActivityMax(BigDecimal ordersInfoActivityMax, String key) {
        ReturnCouponResponse returnCouponResponse = new ReturnCouponResponse();
        // 商品红包
        ordersInfoActivityMax = Optional.ofNullable(ordersInfoActivityMax).orElse(BigDecimal.ZERO);
        // 用户红包
        BigDecimal userActivityMax = new BigDecimal(680);
        // 已使用红包
        BigDecimal usedActivityMax = BigDecimal.ZERO;

        if (StringUtils.isNotEmpty(redisService.get(key))) {// 记录用户返现红包金额
            returnCouponResponse = com.alibaba.fastjson.JSONObject.parseObject(redisService.get(key), ReturnCouponResponse.class);
            // 获取已使用红包
            usedActivityMax = Optional.ofNullable(returnCouponResponse.getUsedActivityMax()).orElse(BigDecimal.ZERO);
            // 获取用户红包
            userActivityMax = Optional.ofNullable(returnCouponResponse.getActivityMax()).orElse(new BigDecimal(680));

        } else {
            returnCouponResponse.setTotalReturnCoupon(BigDecimal.ZERO);
        }
        // 累计已使用红包
        ordersInfoActivityMax = usedActivityMax.add(ordersInfoActivityMax).setScale(2, BigDecimal.ROUND_HALF_UP);
        // 扣减用户红包
        if (ordersInfoActivityMax.compareTo(userActivityMax) > 0) {
            userActivityMax = BigDecimal.ZERO;
        } else {
            userActivityMax = userActivityMax.subtract(ordersInfoActivityMax).setScale(2, BigDecimal.ROUND_HALF_UP);
        }

        returnCouponResponse.setUsedActivityMax(ordersInfoActivityMax);
        returnCouponResponse.setActivityMax(userActivityMax);
        redisService.set(key, com.alibaba.fastjson.JSONObject.toJSONString(returnCouponResponse));
        redisService.expire(key, TokenConstants.EXPIRE_SECONDS);
    }


    private void addUsedSubsidy(OrdersInfo ordersInfo, String recordKey) {
        RecordSubsidyDataDto recordSubsidyDataDto = new RecordSubsidyDataDto();

        String recordSubsidyObj = redisService.get(recordKey);
        if (StringUtils.isNotEmpty(recordSubsidyObj)) {
            recordSubsidyDataDto = com.alibaba.fastjson.JSONObject.parseObject(recordSubsidyObj, RecordSubsidyDataDto.class);
        }

        BigDecimal received = Optional.ofNullable(recordSubsidyDataDto.getReceived())
                .orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal used = Optional.ofNullable(recordSubsidyDataDto.getUsed())
                .orElse(BigDecimal.ZERO)
                .add(ordersInfo.getActivityMax()).setScale(2, BigDecimal.ROUND_HALF_UP);

        if (used.compareTo(received) > 0) {
            received = used;
        }

        recordSubsidyDataDto.setUsed(used);
        recordSubsidyDataDto.setReceived(received);
        recordSubsidyDataDto.setToken(Optional.ofNullable(recordSubsidyDataDto.getToken()).orElse(TokenUtil.getToken()));
        recordSubsidyDataDto.setReceiveTime(Optional.ofNullable(recordSubsidyDataDto.getReceiveTime()).orElse(new Date()));

        redisService.set(recordKey, com.gexin.fastjson.JSON.toJSONString(recordSubsidyDataDto));
        redisService.expire(recordKey, ExpireTimeConstant.SUBSIDY_DATA_TIME);
    }

    private void addUsedSubsidy(OrdersInfo ordersInfo, String recordKey, Integer userId) {
        log.info("===userId={}===", userId);

        String key = RedisConstants.RECORD_SUBSIDYKEY_USE_APP  + userId;
        String recordSubsidyObj = "0";
        try {
            recordSubsidyObj = redisService.get(key);
        } catch (Exception e) {}
        BigDecimal used = BigDecimal.ZERO;
        if (StringUtils.isNotEmpty(recordSubsidyObj)) {
            used = BigDecimal.valueOf(Double.valueOf(recordSubsidyObj))
                    .add(ordersInfo.getActivityMax())
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        }else {
            used = BigDecimal.ZERO
                    .add(ordersInfo.getActivityMax())
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        redisService.set(key, used.toString());
        redisService.expire(recordKey, Integer.parseInt(subsidyDay) * 24 * 60 * 60);
    }

    private boolean check(Map<String, String> params) throws AlipayApiException {
        boolean verifyResult = false;

        String outTradeNo = params.get("out_trade_no");
        OrdersPayExample ordersExample = new OrdersPayExample();
        ordersExample.createCriteria().andResOrderNoEqualTo(outTradeNo);
        List<OrdersPay> orders = ordersPayMapper.selectByExample(ordersExample);

        if (orders.size() > 0) {
            OrdersPay payedOrder = orders.get(0);

            if (!new BigDecimal(params.get("total_amount")).multiply(new BigDecimal(100)).equals(payedOrder.getAmount().multiply(new BigDecimal(100)))) {
                throw new AlipayApiException("error total_amount");
            }

            //优先走数据库配置
            Integer payConfigId = payedOrder.getPayConfigId();
            if(payConfigId!=null){
                YxAlipayConfig alipayConfig = payConfigDao.findAliPayById(payConfigId);
                if (alipayConfig!=null){
                    verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), "UTF-8", alipayConfig.getSignType());
                }
            }else{
                return true;
            }
            return verifyResult;
        }
        throw new AlipayApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.OUT_TRADE_NO_ERROR));
    }

    /**
     * 将request中的参数转换成Map
     */
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<String, String>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }

    private AlipayNotifyResponse buildAlipayNotifyParam(Map<String, String> params) {
        String json = JSON.toJSONString(params);
        return JSON.parseObject(json, AlipayNotifyResponse.class);
    }

    @Transactional(rollbackFor = Exception.class)
    public Integer fullDeduction(AlipayOrderRequest request) {
        Orders orders = ordersMapper.selectByPrimaryKey(request.getOrderId());
        BigDecimal realTotalMoney = orders.getRealTotalMoney();
        // 直接修改订单状态
        orders.setOrderRemarks(request.getDesc());
        orders.setIsAnonymity(request.getIsAnonymity());
        orders.setPayType(OrderPayTypeEnums.deduction.name());
        orders.setIsPay(IsPayConstant.YES);
        orders.setOrderStatus(OrderStatusEnums.UNSHIPPED.getValue());
        orders.setRealTotalMoney(BigDecimal.ZERO);
        orders.setDeductionMoney(realTotalMoney);
        orders.setPayTime(new Date());
        if (request.getAddressId() != null) {
            DefaultAddressDto address = usersClient.getOneAddress(orders.getUserId(), request.getAddressId());
            orders.setProvince(address.getProvince());
            orders.setCity(address.getCity());
            orders.setAddress(address.getAddress());
            orders.setArea(address.getArea());
            orders.setUserAddress(address.getProvince() + address.getCity() + address.getArea() + address.getAddress());
            orders.setUserName(address.getName());
            orders.setUserPhone(address.getTel());
        }
        if (null != request.getRealNameId()) {
            orders.setRealNameId(request.getRealNameId());
        }
        ordersMapper.updateByPrimaryKeySelective(orders);
        UserBalanceDto userBalanceDto = new UserBalanceDto();
        userBalanceDto.setUserId(orders.getUserId());
        userBalanceDto.setUpdateMoney(realTotalMoney);
        userBalanceDto.setType("SUB");
        userBalanceDto.setSource(UserBalanceSourceEnums.DEDUCTION.name());
        userBalanceDto.setAmountType(1);
        usersClient.updateMoney(userBalanceDto);

        // 获取订单明细
        OrdersInfoExample ordersInfoExample = new OrdersInfoExample();
        ordersInfoExample.createCriteria()
                .andOrderIdEqualTo(orders.getId());
        List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectByExample(ordersInfoExample);
        ordersInfoList.stream()
                .forEach(item -> {
                    // 修改订单详情状态
                    OrdersInfo ordersInfo = new OrdersInfo();
                    ordersInfo.setId(item.getId());
                    ordersInfo.setOrderinfoStatus(OrderStatusEnums.UNSHIPPED.getValue());
                    ordersInfoMapper.updateByPrimaryKeySelective(ordersInfo);
                    try {
                        if ("h5".equals(TokenUtil.getPlatformData())) {
                            String tokenUser = redisService.get(orders.getH5Token());
                            // 商品 减库存 加销量 店家加销量
                            productService.sellAfter(item.getProductId(), item.getProductSpecId(), item.getProductSum(), item.getProductPrice(),
                                    item.getIsWalletPay(), tokenUser, item.getIsDirectbuy(), item.getActivityType(), item.getActivityMax(), orders.getUserId());
                        } else {
                            // 商品 减库存 加销量 店家加销量
                            productService.sellAfter(item.getProductId(), item.getProductSpecId(), item.getProductSum(), item.getProductPrice(),
                                    item.getIsWalletPay(), item.getIsDirectbuy(), item.getActivityType(), item.getActivityMax(), orders.getUserId());
                        }
                    } catch (Exception e) {
                        log.error(GlobalExceptionHandler.getExceptionToString(e));
                        log.error("减库存发生异常 订单id :{}", item.getId());
                    }
                    if ("h5".equals(TokenUtil.getPlatformData())) {
                        // 删除补贴价格
                        if ("OLD_FOR_NEW".equals(item.getActivityType())) {
                            String key = RedisConstants.SUBSIDYKEY + orders.getH5Token();
                            String subsidyObj = redisService.getMapString(key, item.getProductId().toString());
                            if (StringUtils.isNotEmpty(subsidyObj)) {
                                redisService.delete(key, item.getProductId().toString());
                            }
                        }
                        // 扣除用户的红包余额
                        if ("CASH_COUPON".equals(item.getActivityType())) {
                            this.addUsedActivityMax(item.getActivityMax(), RedisConstants.RETURN_COUPON + orders.getH5Token());//记录用户使用红包金额
                        }
                        //
                        if ("RETURN_COUPON".equals(item.getActivityType())) {
                            this.addReturnCoupon(item.getActivityMax(), RedisConstants.RETURN_COUPON + orders.getH5Token());//记录用户返现红包金额
                        }
                    } else {
                        try {
                            // 删除补贴价格
                            if ("OLD_FOR_NEW".equals(item.getActivityType())) {
                                String key = RedisConstants.SUBSIDYKEY_APP + orders.getH5Token();
                                String subsidyObj = redisService.getMapString(key, item.getProductId().toString());
                                if (StringUtils.isNotEmpty(subsidyObj)) {
                                    redisService.delete(key, item.getProductId().toString());
                                }
                            }
                            // 扣除用户的红包余额
                            if ("CASH_COUPON".equals(item.getActivityType())) {
                                this.addUsedActivityMax(item.getActivityMax(), RedisConstants.RETURN_COUPON_APP + orders.getH5Token());//记录用户使用红包金额
                            }
                            //
                            if ("RETURN_COUPON".equals(item.getActivityType())) {
                                this.addReturnCoupon(item.getActivityMax(), RedisConstants.RETURN_COUPON_APP + orders.getH5Token());//记录用户返现红包金额
                            }
                        } catch (Exception e) {
                        }
                    }

                });
        return orders.getId();
    }


}
